/**
 * @description 仿写 VueRouter 的插件
 * @author xfj
 */

let _Vue = null;

class VueRouter{
    constructor(options) {
        this.options = options || {};
        // 当前采用的路由模式
        this.mode = this.options.mode || 'hash';
        // 路由的配置信息形成 Map
        this.routes = {};
        // 当前路由信息，该数据设置为响应式
        this.route = _Vue.observable({ path: '' });
        // 解析路由的配置信息形成 hashMap
        this._parseRoutes();
        // 解析当前浏览器的路径，展示页面
        this._parseCurrentRoute();
    }

    // 1. Vue.use(Plugin) 注册 Plugin 插件时，如果 Plugin 是个对象，则会调用 Plugin.install 方法
    static install(Vue) {
        // 1. 如果已注册，则不再重复注册
        if(VueRouter.install.hasInstall) return;
        VueRouter.install.hasInstall = true;
        // 2. 将 Vue 挂载到全局上
        _Vue = Vue;
        // 3. 为 Vue 添加全局功能
        Vue.mixin({
            beforeCreate() {
                // 将创建 vue 实例时，传入构造函数的参数 router 挂在到 Vue.prototype
                if(this.$options.router) {
                    Vue.prototype.$router = this.$options.router;
                    Vue.prototype.$route = this.$options.router.route;
                    this.$options.router.init();
                }
            }
        })
    }

    _parseCurrentRoute() {
        let path = '';
        if('hash' === this.mode) {
            path = window.location.hash?.slice(1) || '/';
            window.location.hash = path;
        } else if('history' === this.mode) {
            path = window.location.pathname || '/';
            window.history.pushState(path);
        }
        this.route.path = path;
    }

    // 解析路由配置形成 HashMap
    _parseRoutes() {
        const routes = this.options.routes || [];
        for(let item of routes) {
            if(item.path && item.component) {
                this.routes[item.path] = item.component;
            }
        }
    }   

    init() {
        this._initVueComponent();
        // 重复注册插件，只会添加一次监听
        this._initPopListener();
    }

    // 注册 Vue 全局组件
    _initVueComponent() {
        const self = this;
        // 注册 router-link 组件
        _Vue.component('router-link', {
            props: {
                to: String,
                required: true,
            },
            render(h){
                return h(
                    'a',  
                    {
                        attrs: {
                            href: this.to,
                        },
                        on: {
                            click: this.clickHandler
                        },
                    },
                    this.$slots.default
                );
            },
            methods: {
                clickHandler(e) {
                    e.preventDefault();
                    console.log(self.mode, this.to);
                    if('history' === self.mode) {
                        window.history?.pushState({}, '', this.to);
                    } else if('hash' === self.mode) {
                        window.location.hash = this.to;
                    }
                    self.route.path = this.to;
                }
            }
        });

        // 注册 router-view 组件
        _Vue.component('router-view', {
            render(h) {
                const component = self.routes[self.route.path];
                return h(component);
            }
        })
    }

    // 添加 popState/hashchange 监听
    _initPopListener() {
        if('hash' === this.mode) {
            window.addEventListener('hashchange', () => {
                this.route.path = window.location.hash?.slice(1);
            })
        } else if('history' === this.mode) {
            window.addEventListener('popstate', () => {
                this.route.path = window.location.pathname;
            })
        }
    }

    // VueRouter 上会继承 history 的一些方法和属性
    go(step) {
        if('number' === typeof step) {
            window.history?.go(step);
        }
    }
    push(url) {
        if('string' === typeof url) {
            this.route.path = url;
            if('hash' === this.mode) {
                window.location.hash = url;
            } else if('history' === this.mode) {
                window.history?.pushState({}, '', url);
            }
        }
    }
}

export default VueRouter;
